module ecs {
    /**
     * 管理实体实例
     */
    export class EntityManager extends BaseSystem {
        /** 包含管理器中的所有实体 */
        private _entities: Bag<Entity>;
        private _recycled: BitVector = new BitVector();
        private _entityBitVectors: Bag<BitVector> = new Bag<BitVector>();
        private _limbo: NumberDeque = new NumberDeque();
        private nextId: number;
        /**
         * 创建一个新的EntityManager实例
         * @param initialContainerSize 
         */
        constructor(initialContainerSize: number){
            super();
            this._entities = new Bag<Entity>(initialContainerSize);
        }

        protected processSystem() {}

        public registerEntityStore(bv: BitVector){
            bv.ensureCapacity(this._entities.getCapacity());
            this._entityBitVectors.add(bv);
        }

        /**
         * 检查该实体是否处于活动状态。
         * @param entityId 
         */
        public isActive(entityId: number){
            return !this._recycled.unsafeGet(entityId);
        }

        /**
         * 将实体id解析为唯一的实体实例。这个方法可能会返回一个实体，即使它在世界上不是活动的，如果你需要检查实体是否活动，使用{@link #isActive(int)}。
         * @param entityId 
         */
        protected getEntity(entityId: number){
            return this._entities.get(entityId);
        }

        public createEntityInstance(): Entity{
            return this.obtain();
        }

        private obtain(): Entity{
            if (this._limbo.isEmpty()){
                return this.createEntity(this.nextId ++);
            } else {
                let id = this._limbo.popFirst();
                this._recycled.unsafeClear(id);
                return this._entities.get(id);
            }
        }

        private createEntity(id: number): Entity{
            let e = new Entity(this._world, id);
            if (e.id >= this._entities.getCapacity())
                this.growEntityStores();

            this._entities.set(e.id, e);
            return e;
        }

        private growEntityStores(){
            let newSize = 2 * this._entities.getCapacity();
            this._entities.ensureCapacity(newSize);
            let cm = this._world.getComponentManager();
            cm.ensureCapacity(newSize);

            for (let i = 0, s = this._entityBitVectors.size(); s > i; i ++){
                this._entityBitVectors.get(i).ensureCapacity(newSize);
            }
        }
    }
}